####

# @project: UbunTube
# @version = 0.1a
# @site UbunTube http://www.ubuntube.tk
# @copyright (c) 2009 Mohamed Nashmi
# @license http://opensource.org/licenses/gpl-license.php GNU Public License

####

import threading
import os
import subprocess
import gtk
import gobject
import urllib

import Debug


gobject.threads_init()


class Base(threading.Thread):
    """Base class for a video downloader/importer."""
    def __init__(self, video, link):
        threading.Thread.__init__(self)
        self.video = video #: Video item in the Library.List
        self.link = link #: Could be HTTP link or Local file
        #:Boolean to allow the thread to keep running until all requests are completed
        self.running = False 
        #: The File name of the link or path. Ex: /home/$USER/Ubuntube/test.flv
        self.file = None #:
        #: The name or title of the video
        self.name = None
        
        
    def getDetails(self):
        """Wrapper function that updates and returns the duration,
        and the thumbnail of the video
        """
        duration = self.getDuration()
        thumbnail = self.getScreenShot()
        return duration, thumbnail
        
        
    def getScreenShot(self):
        """Creates a thumbnail/screenshot of the video ad stores it in the
        '.thumbnail' directory.
        """
        TEMPDIR = ".temp/%s" % self.video.id
        thumbnail = ".thumbnails/%s" % self.name
        if os.path.exists(thumbnail):
            return thumbnail
            
        if os.path.exists(TEMPDIR):
            os.system("rm -rf %s" % TEMPDIR)
        cmd = "mplayer -vo jpeg:outdir=%s -frames 1 -ss 3 '%s'" % (TEMPDIR, self.file)
        os.system(cmd)
        
        cmd = "mv '%s/00000001.jpg' '%s'" % (TEMPDIR, thumbnail)
        os.system(cmd)
        cmd = "rm -rf %s" % TEMPDIR
        os.system(cmd)
        return thumbnail

    def getDuration(self):
        """Probes mplayer to retrieve the duration of the video"""
        mplayer = "mplayer -identify -endpos 0 \"%s\"  | grep ID_LENGTH" % self.file
        process = subprocess.Popen([mplayer], shell=True, stdout=subprocess.PIPE)
        length = process.communicate(0)[0]
        duration = length.split("ID_LENGTH=")[1]
        seconds = float(duration) % 60
        if seconds > 0:
            seconds = round(seconds)
            minutes = float(duration) / 60
            minutes = int(minutes)
            if minutes >= 60:
                hours = minutes / 60
                minutes = minutes % 60
                formatDuration = "%s:%s h" % (hours, minutes)
            else:
                formatDuration = "%s:%02d m" %(minutes, seconds)
            return [duration, formatDuration]
        else:
            formatDuration = int(duration) / 60
            formatDuration = "%s" % formatDuration
            return [duration, formatDuration]
        
        
class Internet(gobject.GObject, Base):
    """Inherited class that retrieves videos from Youtube"""
    
    __gsignals__ = {
        "dataRetrieved": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
        "downloaded" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
        "gotVidString" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
        "updateProgress" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
        }
        
        
    def __init__(self, video, link):
        """Creates the Internet class to download the video from youtube.
        
        video = the parent Video Object
        link = the youtube link
        """
        
        Base(video, link)
        threading.Thread.__init__(self)
        self.__gobject_init__()
        self.connect("gotVidString", self.fetchDetails)
        self.video = video
        self.link = link
        self.running = False
        #:Stores the html paged used to retrieve data about the video
        self.tempName = '.temp/%s' % link.split("v=")[1]
        self.file = None
        self.name = None
        #:The actual duration of the video in seconds
        self.duration = "Fetching"
        #:The duration to be displayed in the Library List
        self.formatDuration = "Fetching"
        #:The thumbnail of the video. Defaults to the 'unknown' picture
        self.thumbnail = ".thumbnails/unknown.png"
        
    def fetchDetails(self, Internet):
        """Gets the Video title and the file name and emits the data retrieved signal"""
        self.name = self.getTitle()
        self.file = ".library/" + self.name + ".flv"
        self.emit("dataRetrieved")
                 
    def downloadPage(self):
        """Dowloads the temp html page and store it in the '.temp' directory"""
        #cmd = "wget -c -O \".temp/%s\" %s" % (self.tempName, self.link)
        try:
            urllib.urlretrieve(self.link, self.tempName)
        except Exception, e:
            Debug.debug(e)
            return False
        Debug.debug("DP ok..")
        return True
    
    def downloadVideo(self):
        """Downloads the actual video using wget and stores it in the 
        '.library' folder"""
        videoID = self.getID().split("&title=")[0]
        videoURL = "http://www.youtube.com/get_video?video_id="+videoID

        try:
            f = urllib.urlretrieve(videoURL, self.file, self.progress)
        except Exception, e:
            print "URL Error:",e

        self.running = False
        durations, self.thumbnail = self.getDetails()
        self.duration = durations[0]
        self.formatDuration = durations[1]
        self.emit("downloaded")

    def progress(self, count, block, size):
        percent = int(count * block * 100/size)
        self.formatDuration =  "%2d%%" % percent
        self.emit("updateProgress")

    def getID(self):
        """Returns the unique Youtube Video id of the requested video to
        allow download of that video"""
        videoID = self.videoString.split("&video_id=")[1][:-1]
        return videoID
       
    def getTitle(self):
        """Returns the video title that appears in youtube."""
        title = self.videoString.split("&title=")[1]
        #Remove trailing appostrophe and slashes
        #File names cant have slashes
        title = title.replace('/', '-')[:-1]
        return title
       
    def getString(self):
        """Returns the unique youtube video string which includes
        the unique video id and the title"""
        if self.downloadPage():
            Debug.debug("DWNLADDD")
            cmd = "grep \"video_id=\" \"%s\"" % self.tempName
            #incase we have a few video_id
            #the first one is the one we want
            videos = os.popen(cmd).read().split(";")[0]
            #:stores the video string
            self.videoString = videos
            self.emit("gotVidString")
        else:
            self.name = "Failed to Fetch"
            self.formatDuration = "0:00"
            self.emit("downloaded")
            
   
    def run(self):
        """Starts the thread and keeps it running until the downloaded signal
        has been emitted"""
        self.running = True
        self.getString()
        while self.running:
            pass
            
                 
class Local(gobject.GObject, Base):
    """Inherited class that imports a video from the local system and
    creates a symbolic link to that file
    """
    __gsignals__ = {
        "imported": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
        }
        
    def __init__(self, video, path):
        """Creates the Local Video object
        
        video = the parent Video
        path = the local path to the file
        """
        Base(video, path)
        threading.Thread.__init__(self)
        self.__gobject_init__()
        self.video = video
        self.running = False   
        self.file = path
        self.name = os.path.basename(path)[:-4] #remove the extension
        self.thumbnail = ".thumbnails/unknown.png"
        self.duration = None
                
    def run(self):
        """Start the thread which gets the duration and the thumbnail
        of the video. If the video is newly imported, it creates a sym
        link in the '.library'
        """
        try:
            durations, self.thumbnail = self.getDetails()
            self.duration = durations[0]
            self.formatDuration = durations[1]
            self.emit("imported")
            Debug.debug("Thread OK")
            Debug.debug("VID Imported")
        except:
            self.duration = 0
            self.formatDuration = "0:00"
            self.name = "Error in file "
            self.emit("imported")
        

gobject.type_register(Internet)        
gobject.type_register(Local)
        
     
